<!-- 图片懒加载组件 -->
<template>
  <div 
    ref="containerRef" 
    class="lazy-image-container"
    :class="{ 'loading': isLoading, 'error': hasError }"
  >
    <!-- 占位符 -->
    <div v-if="isLoading" class="placeholder">
      <div class="skeleton" :style="{ width, height }"></div>
    </div>
    
    <!-- 错误状态 -->
    <div v-else-if="hasError" class="error-placeholder" :style="{ width, height }">
      <svg class="error-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
        <path d="M21 19V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 1 2 2h14a2 2 0 0 1 2-2z"/>
        <polyline points="8.5,8.5 15.5,15.5"/>
        <polyline points="15.5,8.5 8.5,15.5"/>
      </svg>
      <span class="error-text">{{ errorText }}</span>
    </div>
    
    <!-- 响应式图片 -->
    <picture v-else>
      <!-- WebP格式支持 -->
      <source 
        v-if="webpSrc" 
        :srcset="webpSrcset || webpSrc" 
        :sizes="sizes"
        type="image/webp"
      />
      
      <!-- AVIF格式支持 -->
      <source 
        v-if="avifSrc" 
        :srcset="avifSrcset || avifSrc" 
        :sizes="sizes"
        type="image/avif"
      />
      
      <!-- 原始格式 -->
      <img
        ref="imageRef"
        :src="currentSrc"
        :srcset="srcset"
        :sizes="sizes"
        :alt="alt"
        :class="imageClass"
        :style="imageStyle"
        :loading="nativeLoading ? 'lazy' : 'eager'"
        :decoding="decoding"
        @load="onLoad"
        @error="onError"
        @click="onClick"
      />
    </picture>
    
    <!-- 加载进度条（可选） -->
    <div v-if="showProgress && isLoading" class="progress-bar">
      <div class="progress-fill" :style="{ width: `${progress}%` }"></div>
    </div>
    
    <!-- 图片预览遮罩（可选） -->
    <div v-if="preview && !isLoading && !hasError" class="preview-overlay" @click="openPreview">
      <svg class="preview-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
        <path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/>
      </svg>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed, watch, nextTick } from 'vue'

interface Props {
  src: string
  alt?: string
  width?: string
  height?: string
  // 响应式图片支持
  srcset?: string
  sizes?: string
  webpSrc?: string
  webpSrcset?: string
  avifSrc?: string
  avifSrcset?: string
  // 懒加载配置
  rootMargin?: string
  threshold?: number
  nativeLoading?: boolean
  // 性能优化选项
  decoding?: 'sync' | 'async' | 'auto'
  fetchPriority?: 'high' | 'low' | 'auto'
  // 功能配置
  placeholder?: string
  errorText?: string
  showProgress?: boolean
  preview?: boolean
  // 样式配置
  imageClass?: string
  containerClass?: string
  fit?: 'contain' | 'cover' | 'fill' | 'none' | 'scale-down'
  position?: string
  // 缓存配置
  cacheKey?: string
  maxAge?: number
}

const props = withDefaults(defineProps<Props>(), {
  alt: '',
  width: '100%',
  height: 'auto',
  rootMargin: '50px',
  threshold: 0.1,
  nativeLoading: false,
  decoding: 'async',
  fetchPriority: 'auto',
  errorText: '图片加载失败',
  showProgress: false,
  preview: false,
  fit: 'cover',
  position: 'center',
  maxAge: 24 * 60 * 60 * 1000 // 24小时
})

const emit = defineEmits<{
  load: [event: Event]
  error: [event: Event]
  click: [event: Event]
  preview: [event: { src: string; alt: string }]
}>()

const containerRef = ref<HTMLElement>()
const imageRef = ref<HTMLImageElement>()
const isLoading = ref(true)
const hasError = ref(false)
const progress = ref(0)
const currentRetry = ref(0)

// 计算最优图片源
const currentSrc = computed(() => {
  if (!props.src) return ''
  
  let src = props.src
  
  // WebP 支持检测
  if (props.webpSrc && supportsWebP()) {
    src = props.webpSrc
  } else if (props.src.includes('cloudinary.com') || props.src.includes('imagekit.io')) {
    const quality = qualityMap[props.quality]
    src = src.includes('?') ? `${src}&${quality}` : `${src}?${quality}`
  }
  
  return src
})

// WebP 支持检测
function supportsWebP(): boolean {
  const canvas = document.createElement('canvas')
  canvas.width = 1
  canvas.height = 1
  return canvas.toDataURL('image/webp').indexOf('data:image/webp') === 0
}

// 图片预加载
function preloadImage(src: string): Promise<void> {
  return new Promise((resolve, reject) => {
    const img = new Image()
    
    // 模拟加载进度
    if (props.showProgress) {
      const interval = setInterval(() => {
        progress.value = Math.min(progress.value + Math.random() * 30, 90)
      }, 100)
      
      const cleanup = () => clearInterval(interval)
      img.onload = () => {
        cleanup()
        progress.value = 100
        setTimeout(resolve, 100)
      }
      img.onerror = () => {
        cleanup()
        reject()
      }
    } else {
      img.onload = () => resolve()
      img.onerror = () => reject()
    }
    
    img.src = src
  })
}

// 重试加载
async function retryLoad() {
  if (currentRetry.value < props.retryCount) {
    currentRetry.value++
    hasError.value = false
    isLoading.value = true
    
    await new Promise(resolve => setTimeout(resolve, props.retryDelay))
    
    try {
      await preloadImage(currentSrc.value)
      isLoading.value = false
    } catch {
      await retryLoad()
    }
  } else {
    hasError.value = true
    isLoading.value = false
  }
}

// 开始加载图片
async function loadImage() {
  if (!currentSrc.value) return
  
  isLoading.value = true
  hasError.value = false
  currentRetry.value = 0
  progress.value = 0
  
  try {
    await preloadImage(currentSrc.value)
    isLoading.value = false
  } catch {
    await retryLoad()
  }
}

// 交叉观察器
let observer: IntersectionObserver | null = null

function setupIntersectionObserver() {
  if (!props.lazy || !containerRef.value) return
  
  observer = new IntersectionObserver(
    (entries) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          loadImage()
          observer?.unobserve(entry.target)
        }
      })
    },
    {
      threshold: props.threshold,
      rootMargin: props.rootMargin
    }
  )
  
  observer.observe(containerRef.value)
}

// 响应式图片工具函数
const generateWebPSrc = (originalSrc: string): string => {
  if (!originalSrc) return ''
  
  // 如果已经是WebP格式，直接返回
  if (originalSrc.toLowerCase().includes('.webp')) {
    return originalSrc
  }
  
  // 简单的WebP转换逻辑（实际应用中可能需要服务端支持）
  return originalSrc.replace(/\.(jpg|jpeg|png)$/i, '.webp')
}

const generateAVIFSrc = (originalSrc: string): string => {
  if (!originalSrc) return ''
  
  // 如果已经是AVIF格式，直接返回
  if (originalSrc.toLowerCase().includes('.avif')) {
    return originalSrc
  }
  
  // 简单的AVIF转换逻辑
  return originalSrc.replace(/\.(jpg|jpeg|png|webp)$/i, '.avif')
}

// 计算属性
const webpSrc = computed(() => props.webpSrc || generateWebPSrc(props.src))
const avifSrc = computed(() => props.avifSrc || generateAVIFSrc(props.src))

const imageStyle = computed(() => ({
  objectFit: props.fit,
  objectPosition: props.position,
  width: props.width,
  height: props.height,
  transition: 'opacity 0.3s ease-in-out'
}))

// 缓存管理
const imageCache = new Map<string, { data: string; timestamp: number }>()

const getCachedImage = (src: string): string | null => {
  if (!props.cacheKey) return null
  
  const cached = imageCache.get(props.cacheKey)
  if (cached && Date.now() - cached.timestamp < props.maxAge) {
    return cached.data
  }
  
  return null
}

const setCachedImage = (src: string, data: string): void => {
  if (!props.cacheKey) return
  
  imageCache.set(props.cacheKey, {
    data,
    timestamp: Date.now()
  })
}

// 性能监控
const loadStartTime = ref<number>(0)
const performanceEntry = ref<PerformanceResourceTiming | null>(null)

const trackImagePerformance = (src: string) => {
  loadStartTime.value = performance.now()
  
  // 监听资源加载完成
  nextTick(() => {
    const observer = new PerformanceObserver((list) => {
      const entries = list.getEntries()
      const imageEntry = entries.find(entry => entry.name.includes(src)) as PerformanceResourceTiming
      
      if (imageEntry) {
        performanceEntry.value = imageEntry
        console.log(`图片加载性能: ${src}`, {
          duration: imageEntry.duration,
          transferSize: imageEntry.transferSize,
          decodedBodySize: imageEntry.decodedBodySize
        })
      }
      
      observer.disconnect()
    })
    
    observer.observe({ entryTypes: ['resource'] })
  })
}

// 事件处理
const onLoad = (event: Event) => {
  const img = event.target as HTMLImageElement
  isLoading.value = false
  hasError.value = false
  
  // 性能统计
  const loadTime = performance.now() - loadStartTime.value
  console.log(`图片加载完成: ${loadTime.toFixed(2)}ms`)
  
  // 缓存图片
  if (props.cacheKey) {
    setCachedImage(props.src, img.src)
  }
  
  emit('load', event)
}

const onError = (event: Event) => {
  isLoading.value = false
  hasError.value = true
  
  console.warn('图片加载失败:', props.src)
  emit('error', event)
}

const onClick = (event: MouseEvent) => {
  emit('click', event)
}

const openPreview = () => {
  if (props.preview) {
    // 这里可以集成图片预览组件
    emit('preview', { src: currentSrc.value, alt: props.alt })
  }
}

// 监听 src 变化
watch(() => props.src, () => {
  if (!props.lazy) {
    loadImage()
  }
})

onMounted(() => {
  if (props.lazy) {
    setupIntersectionObserver()
  } else {
    loadImage()
  }
})

onUnmounted(() => {
  observer?.disconnect()
})

// 图片格式检测函数
const detectWebPSupport = (): Promise<boolean> => {
  return new Promise((resolve) => {
    const webP = new Image()
    webP.onload = webP.onerror = () => resolve(webP.height === 2)
    webP.src = ''
  })
}

const detectAVIFSupport = (): Promise<boolean> => {
  return new Promise((resolve) => {
    const avif = new Image()
    avif.onload = avif.onerror = () => resolve(avif.height === 2)
    avif.src = ''
  })
}

// 暴露给模板使用
defineExpose({
  detectWebPSupport,
  detectAVIFSupport
})
</script>

<style scoped>
.lazy-image-container {
  position: relative;
  display: inline-block;
  overflow: hidden;
}

.placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
}

.skeleton {
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: loading 1.5s infinite;
  border-radius: 4px;
}

@keyframes loading {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}

.error-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background-color: #f5f5f5;
  color: #999;
  border-radius: 4px;
  padding: 20px;
}

.error-icon {
  width: 48px;
  height: 48px;
  margin-bottom: 8px;
  opacity: 0.5;
}

.error-text {
  font-size: 14px;
  text-align: center;
}

.progress-bar {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 2px;
  background-color: rgba(0, 0, 0, 0.1);
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #007bff, #0056b3);
  transition: width 0.3s ease;
}

img {
  display: block;
  max-width: 100%;
  height: auto;
  transition: opacity 0.3s ease;
}

.loading img {
  opacity: 0;
}

.error img {
  display: none;
}

/* 响应式图片 */
@media (max-width: 768px) {
  .skeleton {
    min-height: 200px;
  }
}

/* 深色模式支持 */
@media (prefers-color-scheme: dark) {
  .skeleton {
    background: linear-gradient(90deg, #2a2a2a 25%, #3a3a3a 50%, #2a2a2a 75%);
  }
  
  .error-placeholder {
    background-color: #2a2a2a;
    color: #ccc;
  }
}
</style>